﻿using System;
using System.CodeDom.Compiler;
using System.Reflection;
using Microsoft.JScript;

///
/// Implements JScript/JavaScript Eval like
/// functionality in C# to allow dynamic evaluation
/// of expressions.
///
public static class Evaluator
{
    #region Private Members

    private static Type _evaluatorType;
    private static object _evaluatorInstance;
    private static readonly string _jscriptEvalClass =
    @"import System;
class JScriptEvaluator
{
public static function Eval(expression : String) : String
{
return eval(expression);
}
}";

    #endregion

    #region Private Methods

    ///
    /// Creates a dynamic in-memory assembly using JScript.NET
    /// to evaluate expressions.
    ///
    private static void Initialize()
    {

        CodeDomProvider compiler = new JScriptCodeProvider();

        CompilerParameters parameters = new CompilerParameters();
        parameters.GenerateInMemory = true;
        parameters.ReferencedAssemblies.Add("system.dll");

        CompilerResults results = compiler.CompileAssemblyFromSource(parameters, _jscriptEvalClass);

        Assembly assembly = results.CompiledAssembly;
        _evaluatorType = assembly.GetType("JScriptEvaluator");
        _evaluatorInstance = Activator.CreateInstance(_evaluatorType);
    }

    #endregion

    #region Public Methods

    ///
    /// Evaluates specified expression using reflection
    /// on the assembly generated in Initialize() method.
    ///
    /// The expression.
    /// A string representing evaluated expression.
    public static string Eval(string expression,out string error)
    {
        error = string.Empty;
        if (_evaluatorInstance == null)
            Initialize();
        object result = null;
        try
        {
            result = _evaluatorType.InvokeMember(
                 "Eval",
                BindingFlags.InvokeMethod,
                 null,
                _evaluatorInstance,
                 new object[] { expression }
                );
        }
        catch (Exception ex)
        {
            error = expression + Environment.NewLine + ex.Message;
            result = "";
        }


        return (result == null) ? null : result + "";

    }

    #endregion
}
//using System;
//using System.Data;
//using System.Configuration;
//using System.CodeDom.Compiler;
//using Microsoft.CSharp;
//using System.Text;
//using System.Reflection;
//using System.Collections.Generic;
//using System.Net;
//using System.Text.RegularExpressions;

//namespace ConsolidationTool.Common
//{
//    /// <summary>
//    /// C#代码执行器，提供动态执行C#代码
//    /// </summary>
//    public class Evaluator
//    {
//        private static CSharpCodeProvider cCodeProder = null;
//        private static CompilerParameters compPars = null;
//        private static CompilerResults compResult = null;
//        private static Regex rexLastCode = new Regex(@"(print:).+;\s*$", RegexOptions.Compiled | RegexOptions.IgnoreCase); //用于搜索最后一条代码的位置

//        static Evaluator()
//        {
//            cCodeProder = new CSharpCodeProvider();
//        }

//        /// <summary>
//        /// 执行指定的代码
//        /// </summary>
//        /// <param name="strCodes"></param>
//        /// <returns></returns>
//        public static string Eval(string strCodes, out string strErrText)
//        {
//            #region 编译代码
//            strCodes = strCodes.EndsWith(";") ? strCodes : strCodes + ";";

//            strErrText = InitCompile(ref strCodes);
//            if (strErrText != null) return null;
//            try
//            {
//                compResult = cCodeProder.CompileAssemblyFromSource(compPars, new string[] { strCodes });
//            }
//            catch (NotImplementedException nie)
//            {
//                strErrText = nie.Message;
//                return null;
//            }

//            if (compResult.Errors.HasErrors)
//            {
//                StringBuilder sbErrs = new StringBuilder(strCodes + System.Environment.NewLine);
//                sbErrs.Append("您所提供的C#代码中存在语法错误！" + System.Environment.NewLine);
//                foreach (CompilerError err in compResult.Errors)
//                {
//                    sbErrs.AppendFormat("{0}，{1}" + System.Environment.NewLine, err.ErrorNumber, err.ErrorText);
//                }
//                strErrText = sbErrs.ToString();
//                return null;
//            }
//            #endregion

//            Assembly assembly = compResult.CompiledAssembly;
//            object prgInsl = assembly.CreateInstance("System._ClassEvaluatorCompiler");
//            MethodInfo medInfo = prgInsl.GetType().GetMethod("PrintResult");
//            string strRetn;
//            try
//            {
//                strRetn = medInfo.Invoke(prgInsl, null).ToString();
//                return strRetn;
//            }
//            catch (Exception exMsg)
//            {
//                strErrText = exMsg.Message;
//                return null;
//            }
//        }

//        /// <summary>
//        /// 预编译代码
//        /// </summary>
//        /// <param name="strCodes">待编译的源代码</param>
//        /// <returns>如果错误则返回错误消息</returns>
//        private static string InitCompile(ref string strCodes)
//        {
//            List<string> lstRefs = new List<string>();//代码字符串中的include引用程序集------未使用

//            List<string> lstUsings = new List<string>();//代码字符串中的using引用命名空间


//            #region 分离引用的程序集与命名空间
//            int point = 0;
//            string strTemp;
//            char[] cCodes = strCodes.ToCharArray();
//            for (int i = 0; i < cCodes.Length; ++i)
//            {
//                if (cCodes[i] == '\n' || (cCodes[i] == '\r' && cCodes[i + 1] == '\n'))
//                {
//                    strTemp = strCodes.Substring(point, i - point);
//                    if (strTemp.TrimStart(new char[] { ' ' }).StartsWith("using "))
//                    {
//                        strTemp = strTemp.Substring(6).Trim();
//                        if (!lstUsings.Contains(strTemp))
//                        {
//                            lstUsings.Add(strTemp);
//                        }
//                        else
//                        {
//                            return "预编译失败，代码中不允许包含重复命名空间导入。" + System.Environment.NewLine + "using " + strTemp;
//                        }
//                        point = cCodes[i] == '\n' ? i + 1 : i + 2;
//                        ++i;
//                    }
//                    else if (strTemp.TrimStart(new char[] { ' ' }).StartsWith("include "))
//                    {
//                        strTemp = strTemp.Substring(8).Trim().ToLower();
//                        if (!lstRefs.Contains(strTemp))
//                        {
//                            lstUsings.Add(strTemp);
//                        }
//                        else
//                        {
//                            return "预编译失败，代码中不允许包含重复的程序集引用。" + System.Environment.NewLine + "include " + strTemp;
//                        }
//                        point = cCodes[i] == '\n' ? i + 1 : i + 2;
//                        ++i;
//                    }
//                    else
//                    {
//                        break;
//                    }
//                }
//            }
//            strCodes = strCodes.Substring(point);
//            #endregion

//            #region 初始化编译参数
//            if (compPars == null)
//            {
//                compPars = new CompilerParameters();
//                compPars.GenerateExecutable = false;
//                compPars.GenerateInMemory = true;
//            }
//            //string workDir = System.Web.HttpContext.Current.Server.MapPath("~") + "Bin\\";
//            //string workDir = System.Environment.CurrentDirectory;
//            compPars.ReferencedAssemblies.Clear();
//            compPars.ReferencedAssemblies.Add("system.dll");
//            compPars.ReferencedAssemblies.Add("system.data.dll");
//            compPars.ReferencedAssemblies.Add("system.xml.dll");

//            //compPars.ReferencedAssemblies.Add(workDir + "BLL.dll");
//            //compPars.ReferencedAssemblies.Add(workDir + "Component.dll");
//            //compPars.ReferencedAssemblies.Add(workDir + "Model.dll");
//            //compPars.ReferencedAssemblies.Add(workDir + "Utility.dll");

//            foreach (string str in lstRefs)
//            {
//                compPars.ReferencedAssemblies.Add(str);
//            }
//            #endregion

//            StringBuilder sbRetn = new StringBuilder();

//            #region 生成代码模板
//            ///*为代码添加return 语句*/
//            Match match = rexLastCode.Match(strCodes);
//            if (match.Success)
//            {
//                strCodes = string.Format("{0}\r\nreturn {1}", strCodes.Substring(0, match.Groups[1].Index), strCodes.Substring(match.Groups[1].Index + match.Groups[1].Length));
//            }
//            else
//            {
//                strCodes = "return " + strCodes.Trim();//把要运行的代码字符串作为返回值---作为输出 - 显示运行的字符串源码
//            }

//            /*拼接代码*/
//            foreach (string str in lstUsings)
//            {
//                sbRetn.AppendLine("using " + str);
//            }
//            sbRetn.AppendLine("namespace System{");
//            sbRetn.AppendLine("public class _ClassEvaluatorCompiler{");
//            sbRetn.AppendLine("public static object PrintResult(){");
//            sbRetn.AppendLine(strCodes);
//            sbRetn.AppendLine("}}}");
//            #endregion
//            strCodes = sbRetn.ToString();
//            return null;
//        }


//    }
//}
